package cate.game.role.res.guild.po.basic;

import cate.common.table.d.GDFunc;
import cate.common.table.d.GDGuild;
import cate.common.table.d.GDMail;
import cate.common.table.d.GDOperation;
import cate.common.table.guild.GuildBannerRow;
import cate.common.table.guild.GuildGradeRow;
import cate.common.table.guild.GuildPatternRow;
import cate.common.util.XT;
import cate.game.GameBody;
import cate.game.mail.po.MailBuilder;
import cate.game.res.MixRes;
import cate.game.role.Role;
import cate.game.role.RoleSnapshot;
import cate.game.role.mail.Mail;
import cate.game.role.res.guild.GuildFuncBase;
import cate.game.role.res.guild.msg.basic.GuildBasicResp;
import cate.game.role.res.guild.po.GuildPO;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;
import easy.java.time.DateTool;
import org.springframework.data.annotation.Transient;

import java.util.ArrayList;
import java.util.List;

public class GuildBasicPO extends GuildFuncBase {
  @Transient
  @NoteField(value = "uid")
  public String uid;

  @NoteField(value = "编号")
  public String guildNo;

  @NoteField(value = "旗帜")
  public GuildBanner guildBanner;

  @NoteField(value = "公会等级")
  public int level;

  @NoteField(value = "公会经验")
  public long exp;

  @NoteField(value = "公会总战力", detail = "当前战力")
  public long power;

  @NoteField(value = "公会名")
  public String guildName;

  @NoteField(value = "会长名")
  public String presidentName;

  @NoteField(value = "会长ID")
  public String presidentId;

  @NoteField(value = "会长原始服务器ID")
  public int srvIdOriginPresident;

  @NoteField(value = "成员数量")
  public int memberNum;

  @NoteField(value = "成员上限")
  public int memberLimit;

  @NoteField(value = "验证设置", detail = "开启后才需要进行入会验证")
  public boolean authentication;

  @NoteField(value = "入会等级要求")
  public int levelRequired;

  @NoteField(value = "公会宣言")
  public String declaration;

  @NoteField(value = "公会创建时间")
  public long createTime;

  @NoteField(value = "允许编辑的时间")
  public long editableTime;

  @NoteField(value = "周活跃")
  public int activeWeek;

  @NoteField(value = "战力要求")
  public long powerRequire;

  @NoteField(value = "原始服务器ID")
  public int srvId;

  @NoteField(value = "今日经验累计")
  public int todayExp;

  @NoteField(value = "最后一次更新战力的时间戳")
  public long powerTimeStamp;

  @Override
  public void initialize(GuildPO guild) {
    super.initialize(guild);
    this.uid = guild.uid;
    if (level == 0) {
      level = 1;
    }
    if (srvId == 0) {
      srvId = getFuncDependent().guild.game.config.srvId;
    }
    GuildGradeRow row = getRow();
    if (row == null) {
      return;
    }
    memberLimit = row.memberLimit;
  }

  public EcResult setData(GuildPO guild, Role role, String guildName, int pattern, int background, String guildNo, String declaration, boolean authentication, int levelRequire, long powerRequire) {
    String dc = declaration != null ? declaration : "";
    EcResult r = new EcResult();
    this.guildNo = guildNo;
    this.guildName = guildName;
    this.guildBanner = new GuildBanner(pattern, background);
    this.presidentName = role.getBase().name;
    this.presidentId = role.getUid();
    this.srvIdOriginPresident = role.getBase().srvIdOrigin;
    this.memberNum = GDGuild.basic.DEFAULT_GUILD_CREATE_NUM;
    this.authentication = authentication;
    this.levelRequired = levelRequire;
    EcResult rName = guild.game.res.guild.action.checkDeclaration(role, dc);
    if (!rName.ok()) {
      return rName;
    }
    this.declaration = dc;
    this.createTime = System.currentTimeMillis();
    this.powerRequire = powerRequire;
    this.srvId = guild.game.config.srvId;
    return r.success();
  }


  /**
   * 公会验证条件修改
   */
  public void changeAuthentication(Role role, boolean authentication, int levelRequired, long powerRequired) {
    byte pos = role.getRes().guild.getPos();
    if (pos == GDGuild.position.MEMBER) {
      role.getGame().notice.message(role, 310403, "只有长老及以上级别成员可以修改公会验证条件");
      return;
    }
    this.authentication = authentication;
    this.powerRequire = powerRequired;
    this.levelRequired = levelRequired;
    // 通知在线成员公会基本信息修改
    this.noticeUpdateAll();
    role.getGame().notice.message(role, 310404, "验证条件修改成功");
  }


  /**
   * 通知全公会在线玩家变更
   */
  public void noticeUpdateAll() {
    getFuncDependent().guild.member.getOnlineRole().forEach(this::noticeUpdate);
  }

  /**
   * 通知单个玩家公会基础信息变跟
   */
  public void noticeUpdate(Role role) {
    role.sendNow(new GuildBasicResp(this));
  }

  private void warnEditableTime(Role role) {
    role.getGame().notice.message(role, "你的公会因公会名/宣言涉及不良言论被禁止修改，禁止时间至：" + DateTool.instance().format(this.editableTime));
  }

  /**
   * 公会名称修改
   */
  public void changeGuildName(Role role, String guildName) {
    if (!guildFuncOpenCheck(role)) {
      return;
    }
    if (role.getGame().time.now() < this.editableTime) {
      warnEditableTime(role);
      return;
    }
    if (role.getRes().guild.getPos() != GDGuild.position.PRESIDENT) {
      role.getGame().notice.message(role, 310405, "仅有会长可以修改公会名称");
      return;
    }
    // 公会名称检测
    EcResult rName = role.getGame().res.guild.action.checkGuildName(role, guildName, role.getRes().guild.uid);
    if (!rName.ok()) {
      return;
    }
    // 看看改名费够不够
    EcResult rConsume = new MixRes(GDGuild.basic.CHANGE_NAME_COST).consume(role, null);
    if (!rConsume.ok()) {
      role.getGame().notice.message(role, "费用不足");
      return;
    }
    // 满足条件则开始改名
    this.guildName = guildName;
    // 通知在线成员公会基本信息修改
    this.noticeUpdateAll();
    role.getGame().notice.message(role, 310406, "公会名称修改成功");
  }

  /**
   * 公会宣言修改
   */
  public void changeDeclaration(Role role, String declaration) {
    if (!guildFuncOpenCheck(role)) {
      return;
    }
    if (role.getGame().time.now() < this.editableTime) {
      warnEditableTime(role);
      return;
    }
    byte pos = role.getRes().guild.getPos();
    GameBody game = role.getGame();
    if (pos != GDGuild.position.PRESIDENT && pos != GDGuild.position.VICE_PRESIDENT) {
      game.notice.message(role, 310407, "只有会长和副会长可以修改公会宣言");
      return;
    }
    String dc = declaration != null ? declaration : "";
    // 公会宣言检测
    EcResult rName = game.res.guild.action.checkDeclaration(role, dc);
    if (!rName.ok()) {
      return;
    }
    // 满足条件则开始改名
    this.declaration = dc;
    // 通知在线成员公会基本信息修改
    this.noticeUpdateAll();
    game.notice.message(role, 310408, "公会宣言修改成功");
  }


  @Transient
  @JsonIgnore
  public GuildGradeRow getRow() {
    return getFuncDependent().guild.game.table.guild.grade.get(level);
  }


  public void addExp(int value) {
    GuildGradeRow gradeRow = getRow();
    if (gradeRow == null) {
      return;
    }
    int requireExp = gradeRow.requireExp;

    if (requireExp == -1) {
//            "已经升至最高级"
      return;
    }

    int limit = gradeRow.memberLimit * GDGuild.PER_MEMBER_GUILD_EXP;
    if (limit <= this.todayExp) {
      return;
    }

    this.todayExp += value;
    if (this.todayExp > limit) {
      value -= (this.todayExp - limit);
      if (value > 0) {
        this.exp += value;
      }
    } else {
      this.exp += value;
    }


    requireExp = gradeRow.requireExp;

    if (requireExp == -1) {
//            "已经升至最高级"
      return;
    }

    //检测是否能自动升级
    if (this.exp >= requireExp) {
      getFuncDependent().guild.basic.levelUp();
      this.exp -= requireExp;
      List<Object> params = new ArrayList<>();
      params.add(getFuncDependent().guild.basic.guildName);
      params.add(getFuncDependent().guild.basic.level);
      Mail m =
              new MailBuilder()
                      .setContentId(GDMail.Tid.GUILD_LEVEL_UP)
                      .setParamList(params)
                      .setOperation(GDOperation.NULL)
                      .build();
      getFuncDependent().guild.member.getOnlineRole().forEach(a -> getFuncDependent().guild.game.mail.send(a.getUid(), m));
    }
    noticeUpdateAll();
  }

  public void gmAddExp(int value) {
    this.exp += value;
    GuildGradeRow gradeRow = getRow();
    int requireExp = gradeRow.requireExp;
    while (this.exp >= requireExp && requireExp != -1) {
      getFuncDependent().guild.basic.levelUp();
      this.exp -= requireExp;
      List<Object> params = new ArrayList<>();
      params.add(getFuncDependent().guild.basic.guildName);
      params.add(getFuncDependent().guild.basic.level);
      Mail m =
              new MailBuilder()
                      .setContentId(GDMail.Tid.GUILD_LEVEL_UP)
                      .setParamList(params)
                      .setOperation(GDOperation.NULL)
                      .build();
      getFuncDependent().guild.member.getOnlineRole().forEach(a -> getFuncDependent().guild.game.mail.send(a.getUid(), m));
      gradeRow = getRow();
      requireExp = gradeRow.requireExp;
    }
  }


  public void levelUp() {
    this.level++;
    this.memberLimit = getRow().memberLimit;
    this.noticeUpdateAll();
  }

  public void randomData(RoleSnapshot snap, String guildName, String guildNo, GameBody game) {
    this.guildNo = guildNo;
    this.guildName = guildName;
    List<GuildBannerRow> backList = game.table.guild.bannerBack.getList();
    int back = backList.get(XT.randomIndex(backList.size())).id;
    List<GuildPatternRow> patternList = game.table.guild.bannerPattern.getList();
    int pattern = patternList.get(XT.randomIndex(patternList.size())).id;
    guildBanner = new GuildBanner(back, pattern);
    presidentName = snap.base.name;
    presidentId = snap.uid;
    srvIdOriginPresident = snap.base.srvIdOrigin;
    memberNum = GDGuild.basic.DEFAULT_GUILD_CREATE_NUM;
    authentication = GDGuild.basic.DEFAULT_GUILD_AUTHENTICATION;
    levelRequired = GDGuild.basic.DEFAULT_GUILD_LEVEL_REQUIRED;
    declaration = GDGuild.basic.DEFAULT_GUILD_DECLARATION;
    createTime = System.currentTimeMillis();
    srvId = game.config.srvId;
  }


  @Override
  public int getFuncId() {
    return GDFunc.GuildFunc.GUILD;
  }

  public void setBanner(int pattern, int background) {
    if (!guildFuncOpenCheck()) {
      return;
    }
    guildBanner.setBanner(pattern, background);
  }

  public void onDaySpan() {
    this.todayExp = 0;
  }
}
